1 Introduction

Generalized map of soil phosphorus retention potential

Generalized map of soil phosphorus retention potential

In this 2011 ISRIC map we can distinguish 16 different main classes of map unit according to its soil phosphorus retention potential.

2 Starting with the wrong file

So I naively assumed that the the geotif available at the ISRIC website contains the same information as the map above.

library(soilP)      # Phosphorus maps
library(raster)
library(rasterVis)  # Plot categorical raster
data_dir <- system.file("data", package = "soilP", mustWork = TRUE)
extdata_dir <- system.file("extdata", package = "soilP", mustWork = TRUE)
test_tif <- file.path(extdata_dir,
            "Global_distribution_of_soil_phosphorus_retention_potential",
            "Global_distribution_of_soil_phosphorus_retention_potential.tif")
test_raster <- raster(test_tif) 

However, when we plot the raster file we get a suspiciously unexpected distribuition of soil phosphorus retention potential:

op <- par()
par(mar = c(0, 0, 0, 0), oma = c(0, 0, 0, 0))
plot(test_raster, axes = FALSE, box = FALSE,
     frame.plot = FALSE,
     legend.width = 2,
     legend.shrink = 0.95,
     axis.args = list(cex.axis = 2),
     legend.args = list(text = "", cex = 1))
par(op)

With the lowest values in Africa and then ascending through Asia, the Americas, Oceania and the highest values in Europe.

After inspection of the Arcgis files and the Batjes 2011 report, I can infer that the values in this geotif seem to be indices of different FAO soil unit domains. They do not represent directly the phosphorus retention potential contrary to what the file name seems to imply. Using that index and a series of SQL queries the author assigns phosphorus retention potential classes to each pixel/map unit in the map.

3 Where did soilclass data came from?

See the manual for details.

?soilclass

3.1 Extracting palette from Arcgis P_retention_class_main layer.

This operation was carried out in ArcGis on the mxd file. I just copied to the corresponding soilclass column r,g,b, the RGB values from the legend of the unique values symbology in the layer P_retention_class_main properties.

soilclass <- read.csv(file.path(extdata_dir,"P_retention_class.csv")) 
soilclass

3.2 Adding hexadecimal strings and R standard names to colors.

color_hex <- apply(soilclass %>% dplyr::select(r,g,b), 
                   1, 
                   function(x){rgb(x[1], x[2], x[3],
                                   maxColorValue = 255)
                   })
color_name <- sapply(sapply(color_hex, plotrix::color.id), 
                       `[[`, 
                       1) # extracts first of multiple possible names
  
soilclass$color_hex <- color_hex
soilclass$color_name <- color_name
soilclass

3.3 Reordering according to ascending Phosphorus Retention Potential.

This is step is critical for rendering color legend in the right way (reproducing arcgis appearance of the generalized map).

The ascending column integers were manually assigned. For the Low map unit main class, higher percentage of Low soil unit P retention corresponded to lower integers. For the Moderate, High, and very High map unit main classes, higher integers were assigned to higher percentage of corresponding soil unit P retention. This means the higher the Low soil unit P retention percentage the lower the integer, and complentarily the higher the Moderate, High, and Very High soil unit P retention percentage the higher the integer. This assignation is naive and consequently both, intuitive and ad hoc.


TODO: We should establish a data based order of map unit soil phosphorus retention classes instead of postulating an ad hoc order. This can be done through selecting the first discriminant dimension from a Discriminant Analysis of the percentage of soil unit phosphorus retention classes per mapping unit. Furthermore, we can use that discriminant dimention as a continuous variable instead of the discrete classes for downstream analyses.


soilclass <- soilclass[order(soilclass$ascending),]
save(soilclass, file = file.path(data_dir,"soilclass.RData"))
soilclass

4 Reading ISRIC map from the geotiff file

tif_in <- file.path(extdata_dir, "tif",
                    "P_retention_potential_main_grey.tif")
tif_out <- file.path( extdata_dir, "tif",
                       "P_retention_potential_main_grey_ascending.tif")
ISRIC2011 <- read_P_ISRIC(tif       = tif_in,
                          soilclass = soilclass,
                          is        = "arcgis",
                          becomes   = "ascending",
                          filename  = tif_out)

5 Adding Raster Attribute Table to ISRIC2011

levels<- S3 method is internal to raster package and could not be exported to the soilP package, which prevented me from making a working package function out of the following snippet:

# Raster Attribute Table
rat <- levels(ISRIC2011)[[1]] %>% 
       dplyr::inner_join(soilclass, by = c("ID" = "ascending"))
levels(ISRIC2011) <- rat # This assignment method is not exported from raster
save(ISRIC2011, file = file.path(data_dir, "ISRIC2011.RData"))

5.1 Raster Plot

op <- par()
par(mar = c(0, 0, 0, 0), oma = c(0, 0, 0, 0))
plot(ISRIC2011, axes = FALSE, box = FALSE,
     frame.plot = FALSE,
     legend.width = 2,
     legend.shrink = 0.95,
     axis.args = list(breaks=1:14, at = 0:15, cex.axis = 2),
     legend.args = list(text = "", cex = 1))
par(op)

5.2 Pixel density histogram

ISRIC2011_hist <- hist(ISRIC2011,maxpixels = ncell(ISRIC2011),
                       breaks = c(0, 0.99 + 0:15), xlab = "value",
                       main = "Phosphorus Retention Potential")

6 Rebuilding the arcgis render appeareance

From the data, the color and the value correspondence between the arcgis 8bit and ascending order.

op <- par()
par(mar = c(0, 0, 0, 0), oma = c(0, 0, 0, 0))
plot(ISRIC2011, 
     col = soilclass$color_hex[1:16],
     breaks = c(0,0.99 + 0:15),
     axes = FALSE, box = FALSE,
     frame.plot = FALSE,
     legend.width = 2,
     legend.shrink = 0.95,
     axis.args = list(at       = c(0,0.99 + 0:15),
                      labels   = c("",0:15), 
                      cex.axis = 2),
     legend.args = list(text = "", cex = 1))
par(op)

However, the raster plot legend above assumes a continuous scale from 0 to 15, while the data is explicitly a categorical variable (although derived from continuous percentages, see Batjes 2011).

7 Using rasterVis to appropiately label categories and show legend

Remember that we assigned to the to the phosphorus retention potential main classes an ad hoc order so we can interpret a direction of ascending retention potential (see above) in the plot legend.

In order to show the right labels in this ascending scale we use the levelplot function from RasterVis that uses the raster attribute table to transform the numerical value of the raster to discrete categories.

levelplot(ISRIC2011, att = "main", col.regions = soilclass$color_hex[1:16],
          maxpixels = ncell(ISRIC2011),  scales = list(draw = FALSE),
          xlab = NULL, ylab = NULL,
          main = "Generalized Phosphorus Retention Potential Map")

LS0tCnRpdGxlOiAiQnVpbGRpbmcgdGhlIHNvaWxjbGFzcyBkYXRhZnJhbWUiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQojIEludHJvZHVjdGlvbgogCiFbR2VuZXJhbGl6ZWQgbWFwIG9mIHNvaWwgcGhvc3Bob3J1cyByZXRlbnRpb24gcG90ZW50aWFsXShJU1JJQzIwMTEucG5nKQoKSW4gdGhpcyAyMDExIElTUklDIG1hcCB3ZSBjYW4gZGlzdGluZ3Vpc2ggMTYgZGlmZmVyZW50IG1haW4gY2xhc3NlcyBvZiBtYXAgdW5pdAphY2NvcmRpbmcgdG8gaXRzIHNvaWwgcGhvc3Bob3J1cyByZXRlbnRpb24gcG90ZW50aWFsLgoKCiMgU3RhcnRpbmcgd2l0aCB0aGUgd3JvbmcgZmlsZQoKU28gSSBuYWl2ZWx5IGFzc3VtZWQgdGhhdCB0aGUgdGhlIGdlb3RpZiBhdmFpbGFibGUgYXQgdGhlIElTUklDIHdlYnNpdGUgY29udGFpbnMKdGhlIHNhbWUgaW5mb3JtYXRpb24gYXMgdGhlIG1hcCBhYm92ZS4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSJoaWRlIn0KbGlicmFyeShzb2lsUCkgICAgICAjIFBob3NwaG9ydXMgbWFwcwpsaWJyYXJ5KHJhc3RlcikKbGlicmFyeShyYXN0ZXJWaXMpICAjIFBsb3QgY2F0ZWdvcmljYWwgcmFzdGVyCgpkYXRhX2RpciA8LSBzeXN0ZW0uZmlsZSgiZGF0YSIsIHBhY2thZ2UgPSAic29pbFAiLCBtdXN0V29yayA9IFRSVUUpCmV4dGRhdGFfZGlyIDwtIHN5c3RlbS5maWxlKCJleHRkYXRhIiwgcGFja2FnZSA9ICJzb2lsUCIsIG11c3RXb3JrID0gVFJVRSkKCnRlc3RfdGlmIDwtIGZpbGUucGF0aChleHRkYXRhX2RpciwKICAgICAgICAgICAgIkdsb2JhbF9kaXN0cmlidXRpb25fb2Zfc29pbF9waG9zcGhvcnVzX3JldGVudGlvbl9wb3RlbnRpYWwiLAogICAgICAgICAgICAiR2xvYmFsX2Rpc3RyaWJ1dGlvbl9vZl9zb2lsX3Bob3NwaG9ydXNfcmV0ZW50aW9uX3BvdGVudGlhbC50aWYiKQp0ZXN0X3Jhc3RlciA8LSByYXN0ZXIodGVzdF90aWYpIApgYGAKCkhvd2V2ZXIsIHdoZW4gd2UgcGxvdCB0aGUgcmFzdGVyIGZpbGUgd2UgZ2V0IGEgc3VzcGljaW91c2x5IHVuZXhwZWN0ZWQKZGlzdHJpYnVpdGlvbiBvZiBzb2lsIHBob3NwaG9ydXMgcmV0ZW50aW9uIHBvdGVudGlhbDoKCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0xMCwgd2FybmluZz1GQUxTRX0Kb3AgPC0gcGFyKCkKcGFyKG1hciA9IGMoMCwgMCwgMCwgMCksIG9tYSA9IGMoMCwgMCwgMCwgMCkpCnBsb3QodGVzdF9yYXN0ZXIsIGF4ZXMgPSBGQUxTRSwgYm94ID0gRkFMU0UsCiAgICAgZnJhbWUucGxvdCA9IEZBTFNFLAogICAgIGxlZ2VuZC53aWR0aCA9IDIsCiAgICAgbGVnZW5kLnNocmluayA9IDAuOTUsCiAgICAgYXhpcy5hcmdzID0gbGlzdChjZXguYXhpcyA9IDIpLAogICAgIGxlZ2VuZC5hcmdzID0gbGlzdCh0ZXh0ID0gIiIsIGNleCA9IDEpKQpwYXIob3ApCmBgYApXaXRoIHRoZSBsb3dlc3QgdmFsdWVzIGluIEFmcmljYSBhbmQgdGhlbiBhc2NlbmRpbmcgdGhyb3VnaCBBc2lhLCB0aGUgQW1lcmljYXMsCk9jZWFuaWEgYW5kIHRoZSBoaWdoZXN0IHZhbHVlcyBpbiBFdXJvcGUuCgpBZnRlciBpbnNwZWN0aW9uIG9mIHRoZSBBcmNnaXMgZmlsZXMgYW5kIHRoZSBCYXRqZXMgMjAxMSByZXBvcnQsIEkgY2FuCmluZmVyIHRoYXQgdGhlIHZhbHVlcyBpbiB0aGlzIGdlb3RpZiBzZWVtIHRvIGJlIGluZGljZXMgb2YgZGlmZmVyZW50IEZBTyBzb2lsCnVuaXQgZG9tYWlucy4gVGhleSBkbyBub3QgcmVwcmVzZW50IGRpcmVjdGx5IHRoZSBwaG9zcGhvcnVzIHJldGVudGlvbiBwb3RlbnRpYWwgCmNvbnRyYXJ5IHRvIHdoYXQgdGhlIGZpbGUgbmFtZSBzZWVtcyB0byBpbXBseS4gVXNpbmcgdGhhdCBpbmRleCBhbmQgYSBzZXJpZXMgb2YKU1FMIHF1ZXJpZXMgdGhlIGF1dGhvciBhc3NpZ25zIHBob3NwaG9ydXMgcmV0ZW50aW9uIHBvdGVudGlhbCBjbGFzc2VzIHRvIGVhY2gKcGl4ZWwvbWFwIHVuaXQgaW4gdGhlIG1hcC4gCgojIFdoZXJlIGRpZCBgc29pbGNsYXNzYCBkYXRhIGNhbWUgZnJvbT8KClNlZSB0aGUgbWFudWFsIGZvciBkZXRhaWxzLgpgYGB7cn0KP3NvaWxjbGFzcwpgYGAKCiMjIEV4dHJhY3RpbmcgcGFsZXR0ZSBmcm9tIEFyY2dpcyBQX3JldGVudGlvbl9jbGFzc19tYWluIGxheWVyLgpUaGlzIG9wZXJhdGlvbiB3YXMgY2FycmllZCBvdXQgaW4gQXJjR2lzIG9uIHRoZSBteGQgZmlsZS4KSSBqdXN0IGNvcGllZCB0byB0aGUgY29ycmVzcG9uZGluZyBgc29pbGNsYXNzYCBjb2x1bW4gYHJgLGBnYCxgYmAsCnRoZSBSR0IgdmFsdWVzIGZyb20gdGhlIGxlZ2VuZCBvZiB0aGUgdW5pcXVlIHZhbHVlcyBzeW1ib2xvZ3kgaW4gdGhlIGxheWVyIApQX3JldGVudGlvbl9jbGFzc19tYWluIHByb3BlcnRpZXMuCgpgYGB7cn0KCnNvaWxjbGFzcyA8LSByZWFkLmNzdihmaWxlLnBhdGgoZXh0ZGF0YV9kaXIsIlBfcmV0ZW50aW9uX2NsYXNzLmNzdiIpKSAKCnNvaWxjbGFzcwpgYGAKCiMjIEFkZGluZyBoZXhhZGVjaW1hbCBzdHJpbmdzIGFuZCBSIHN0YW5kYXJkIG5hbWVzIHRvIGNvbG9ycy4gCmBgYHtyfQpjb2xvcl9oZXggPC0gYXBwbHkoc29pbGNsYXNzICU+JSBkcGx5cjo6c2VsZWN0KHIsZyxiKSwgCiAgICAgICAgICAgICAgICAgICAxLCAKICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpe3JnYih4WzFdLCB4WzJdLCB4WzNdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heENvbG9yVmFsdWUgPSAyNTUpCiAgICAgICAgICAgICAgICAgICB9KQpjb2xvcl9uYW1lIDwtIHNhcHBseShzYXBwbHkoY29sb3JfaGV4LCBwbG90cml4Ojpjb2xvci5pZCksIAogICAgICAgICAgICAgICAgICAgICAgIGBbW2AsIAogICAgICAgICAgICAgICAgICAgICAgIDEpICMgZXh0cmFjdHMgZmlyc3Qgb2YgbXVsdGlwbGUgcG9zc2libGUgbmFtZXMKICAKc29pbGNsYXNzJGNvbG9yX2hleCA8LSBjb2xvcl9oZXgKc29pbGNsYXNzJGNvbG9yX25hbWUgPC0gY29sb3JfbmFtZQpzb2lsY2xhc3MKYGBgCgojIyBSZW9yZGVyaW5nIGFjY29yZGluZyB0byBhc2NlbmRpbmcgUGhvc3Bob3J1cyBSZXRlbnRpb24gUG90ZW50aWFsLgpUaGlzIGlzIHN0ZXAgaXMgY3JpdGljYWwgZm9yIHJlbmRlcmluZyBjb2xvciBsZWdlbmQgaW4gdGhlIHJpZ2h0IHdheQoocmVwcm9kdWNpbmcgYXJjZ2lzIGFwcGVhcmFuY2Ugb2YgdGhlIGdlbmVyYWxpemVkIG1hcCkuCgpUaGUgYGFzY2VuZGluZ2AgY29sdW1uIGludGVnZXJzIHdlcmUgbWFudWFsbHkgYXNzaWduZWQuIEZvciB0aGUgTG93IG1hcCB1bml0Cm1haW4gY2xhc3MsIGhpZ2hlciBwZXJjZW50YWdlIG9mIExvdyBzb2lsIHVuaXQgUCByZXRlbnRpb24gY29ycmVzcG9uZGVkIHRvIGxvd2VyCmludGVnZXJzLiBGb3IgdGhlIE1vZGVyYXRlLCBIaWdoLCBhbmQgdmVyeSBIaWdoIG1hcCB1bml0IG1haW4gY2xhc3NlcywgaGlnaGVyCmludGVnZXJzIHdlcmUgYXNzaWduZWQgdG8gaGlnaGVyIHBlcmNlbnRhZ2Ugb2YgY29ycmVzcG9uZGluZyBzb2lsIHVuaXQgUApyZXRlbnRpb24uIFRoaXMgbWVhbnMgdGhlIGhpZ2hlciB0aGUgTG93IHNvaWwgdW5pdCBQIHJldGVudGlvbiBwZXJjZW50YWdlIHRoZQpsb3dlciB0aGUgaW50ZWdlciwgYW5kIGNvbXBsZW50YXJpbHkgdGhlIGhpZ2hlciB0aGUgTW9kZXJhdGUsIEhpZ2gsIGFuZCBWZXJ5IApIaWdoIHNvaWwgdW5pdCBQIHJldGVudGlvbiBwZXJjZW50YWdlIHRoZSBoaWdoZXIgdGhlIGludGVnZXIuClRoaXMgYXNzaWduYXRpb24gaXMgbmFpdmUgYW5kIGNvbnNlcXVlbnRseSBib3RoLCBpbnR1aXRpdmUgYW5kICphZCBob2MqLgoKLS0tLS0tCgpUT0RPOiBXZSBzaG91bGQgZXN0YWJsaXNoIGEgZGF0YSBiYXNlZCBvcmRlciBvZiBtYXAgdW5pdCBzb2lsIHBob3NwaG9ydXMgCiAgICAgIHJldGVudGlvbiBjbGFzc2VzIGluc3RlYWQgb2YgcG9zdHVsYXRpbmcgYW4gYWQgaG9jIG9yZGVyLiBUaGlzIGNhbiBiZSBkb25lCiAgICAgIHRocm91Z2ggc2VsZWN0aW5nIHRoZSBmaXJzdCBkaXNjcmltaW5hbnQgZGltZW5zaW9uIGZyb20gYSBEaXNjcmltaW5hbnQKICAgICAgQW5hbHlzaXMgb2YgdGhlIHBlcmNlbnRhZ2Ugb2Ygc29pbCB1bml0IHBob3NwaG9ydXMgcmV0ZW50aW9uIGNsYXNzZXMgcGVyCiAgICAgIG1hcHBpbmcgdW5pdC4gRnVydGhlcm1vcmUsIHdlIGNhbiB1c2UgdGhhdCBkaXNjcmltaW5hbnQgZGltZW50aW9uIGFzIGEKICAgICAgY29udGludW91cyB2YXJpYWJsZSBpbnN0ZWFkIG9mIHRoZSBkaXNjcmV0ZSBjbGFzc2VzIGZvciBkb3duc3RyZWFtCiAgICAgIGFuYWx5c2VzLgogICAgICAKLS0tLS0tCgpgYGB7cn0Kc29pbGNsYXNzIDwtIHNvaWxjbGFzc1tvcmRlcihzb2lsY2xhc3MkYXNjZW5kaW5nKSxdCgpzYXZlKHNvaWxjbGFzcywgZmlsZSA9IGZpbGUucGF0aChkYXRhX2Rpciwic29pbGNsYXNzLlJEYXRhIikpCgpzb2lsY2xhc3MKYGBgCgojIFJlYWRpbmcgSVNSSUMgbWFwIGZyb20gdGhlIGdlb3RpZmYgZmlsZQoKYGBge3J9CnRpZl9pbiA8LSBmaWxlLnBhdGgoZXh0ZGF0YV9kaXIsICJ0aWYiLAogICAgICAgICAgICAgICAgICAgICJQX3JldGVudGlvbl9wb3RlbnRpYWxfbWFpbl9ncmV5LnRpZiIpCgp0aWZfb3V0IDwtIGZpbGUucGF0aCggZXh0ZGF0YV9kaXIsICJ0aWYiLAogICAgICAgICAgICAgICAgICAgICAgICJQX3JldGVudGlvbl9wb3RlbnRpYWxfbWFpbl9ncmV5X2FzY2VuZGluZy50aWYiKQoKSVNSSUMyMDExIDwtIHJlYWRfUF9JU1JJQyh0aWYgICAgICAgPSB0aWZfaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgc29pbGNsYXNzID0gc29pbGNsYXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlzICAgICAgICA9ICJhcmNnaXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJlY29tZXMgICA9ICJhc2NlbmRpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lICA9IHRpZl9vdXQpCmBgYAoKIyAgQWRkaW5nIFJhc3RlciBBdHRyaWJ1dGUgVGFibGUgdG8gIGBJU1JJQzIwMTFgCmBsZXZlbHM8LWAgUzMgbWV0aG9kIGlzIGludGVybmFsIHRvIGByYXN0ZXJgIHBhY2thZ2UgYW5kIGNvdWxkIG5vdCBiZSBleHBvcnRlZCAKdG8gdGhlIGBzb2lsUGAgcGFja2FnZSwgd2hpY2ggcHJldmVudGVkIG1lIGZyb20gbWFraW5nIGEgd29ya2luZyBwYWNrYWdlIGZ1bmN0aW9uCm91dCBvZiB0aGUgZm9sbG93aW5nIHNuaXBwZXQ6CgpgYGB7cn0KIyBSYXN0ZXIgQXR0cmlidXRlIFRhYmxlCnJhdCA8LSBsZXZlbHMoSVNSSUMyMDExKVtbMV1dICU+JSAKICAgICAgIGRwbHlyOjppbm5lcl9qb2luKHNvaWxjbGFzcywgYnkgPSBjKCJJRCIgPSAiYXNjZW5kaW5nIikpCgpsZXZlbHMoSVNSSUMyMDExKSA8LSByYXQgIyBUaGlzIGFzc2lnbm1lbnQgbWV0aG9kIGlzIG5vdCBleHBvcnRlZCBmcm9tIHJhc3RlcgoKc2F2ZShJU1JJQzIwMTEsIGZpbGUgPSBmaWxlLnBhdGgoZGF0YV9kaXIsICJJU1JJQzIwMTEuUkRhdGEiKSkKCmBgYAojIyBSYXN0ZXIgUGxvdAoKYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpvcCA8LSBwYXIoKQpwYXIobWFyID0gYygwLCAwLCAwLCAwKSwgb21hID0gYygwLCAwLCAwLCAwKSkKcGxvdChJU1JJQzIwMTEsIGF4ZXMgPSBGQUxTRSwgYm94ID0gRkFMU0UsCiAgICAgZnJhbWUucGxvdCA9IEZBTFNFLAogICAgIGxlZ2VuZC53aWR0aCA9IDIsCiAgICAgbGVnZW5kLnNocmluayA9IDAuOTUsCiAgICAgYXhpcy5hcmdzID0gbGlzdChicmVha3M9MToxNCwgYXQgPSAwOjE1LCBjZXguYXhpcyA9IDIpLAogICAgIGxlZ2VuZC5hcmdzID0gbGlzdCh0ZXh0ID0gIiIsIGNleCA9IDEpKQpwYXIob3ApCmBgYAoKIyMgUGl4ZWwgZGVuc2l0eSBoaXN0b2dyYW0KCmBgYHtyfQpJU1JJQzIwMTFfaGlzdCA8LSBoaXN0KElTUklDMjAxMSxtYXhwaXhlbHMgPSBuY2VsbChJU1JJQzIwMTEpLAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMCwgMC45OSArIDA6MTUpLCB4bGFiID0gInZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgICBtYWluID0gIlBob3NwaG9ydXMgUmV0ZW50aW9uIFBvdGVudGlhbCIpCmBgYCAgCgojIFJlYnVpbGRpbmcgdGhlIGFyY2dpcyByZW5kZXIgYXBwZWFyZWFuY2UgCkZyb20gdGhlIGRhdGEsIHRoZSBjb2xvciBhbmQgdGhlIHZhbHVlIGNvcnJlc3BvbmRlbmNlIGJldHdlZW4gdGhlIGFyY2dpcyA4Yml0CmFuZCBhc2NlbmRpbmcgb3JkZXIuIAoKYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpvcCA8LSBwYXIoKQpwYXIobWFyID0gYygwLCAwLCAwLCAwKSwgb21hID0gYygwLCAwLCAwLCAwKSkKCnBsb3QoSVNSSUMyMDExLCAKICAgICBjb2wgPSBzb2lsY2xhc3MkY29sb3JfaGV4WzE6MTZdLAogICAgIGJyZWFrcyA9IGMoMCwwLjk5ICsgMDoxNSksCiAgICAgYXhlcyA9IEZBTFNFLCBib3ggPSBGQUxTRSwKICAgICBmcmFtZS5wbG90ID0gRkFMU0UsCiAgICAgbGVnZW5kLndpZHRoID0gMiwKICAgICBsZWdlbmQuc2hyaW5rID0gMC45NSwKICAgICBheGlzLmFyZ3MgPSBsaXN0KGF0ICAgICAgID0gYygwLDAuOTkgKyAwOjE1KSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyAgID0gYygiIiwwOjE1KSwgCiAgICAgICAgICAgICAgICAgICAgICBjZXguYXhpcyA9IDIpLAogICAgIGxlZ2VuZC5hcmdzID0gbGlzdCh0ZXh0ID0gIiIsIGNleCA9IDEpKQpwYXIob3ApCmBgYAoKSG93ZXZlciwgdGhlIGByYXN0ZXJgIHBsb3QgbGVnZW5kIGFib3ZlIGFzc3VtZXMgYSBjb250aW51b3VzIHNjYWxlIGZyb20gMCB0byAxNSwKd2hpbGUgdGhlIGRhdGEgaXMgZXhwbGljaXRseSBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIChhbHRob3VnaCBkZXJpdmVkIGZyb20KY29udGludW91cyBwZXJjZW50YWdlcywgc2VlIEJhdGplcyAyMDExKS4gCgojIFVzaW5nIHJhc3RlclZpcyB0byBhcHByb3BpYXRlbHkgbGFiZWwgY2F0ZWdvcmllcyBhbmQgc2hvdyBsZWdlbmQgClJlbWVtYmVyIHRoYXQgd2UgYXNzaWduZWQgdG8gdGhlIHRvIHRoZSBwaG9zcGhvcnVzIHJldGVudGlvbiBwb3RlbnRpYWwgbWFpbgpjbGFzc2VzIGFuICphZCBob2MqIG9yZGVyIHNvIHdlIGNhbiBpbnRlcnByZXQgYSBkaXJlY3Rpb24gb2YgYXNjZW5kaW5nIHJldGVudGlvbiAKcG90ZW50aWFsIChzZWUgYWJvdmUpIGluIHRoZSBwbG90IGxlZ2VuZC4KCkluIG9yZGVyIHRvIHNob3cgdGhlIHJpZ2h0IGxhYmVscyBpbiB0aGlzIGFzY2VuZGluZyBzY2FsZSB3ZSB1c2UgdGhlIGBsZXZlbHBsb3RgCmZ1bmN0aW9uIGZyb20gYFJhc3RlclZpc2AgdGhhdCB1c2VzIHRoZSByYXN0ZXIgYXR0cmlidXRlIHRhYmxlIHRvIHRyYW5zZm9ybSB0aGUgCm51bWVyaWNhbCB2YWx1ZSBvZiB0aGUgcmFzdGVyIHRvIGRpc2NyZXRlIGNhdGVnb3JpZXMuCgoKYGBge3J9CmxldmVscGxvdChJU1JJQzIwMTEsIGF0dCA9ICJtYWluIiwgY29sLnJlZ2lvbnMgPSBzb2lsY2xhc3MkY29sb3JfaGV4WzE6MTZdLAogICAgICAgICAgbWF4cGl4ZWxzID0gbmNlbGwoSVNSSUMyMDExKSwgIHNjYWxlcyA9IGxpc3QoZHJhdyA9IEZBTFNFKSwKICAgICAgICAgIHhsYWIgPSBOVUxMLCB5bGFiID0gTlVMTCwKICAgICAgICAgIG1haW4gPSAiR2VuZXJhbGl6ZWQgUGhvc3Bob3J1cyBSZXRlbnRpb24gUG90ZW50aWFsIE1hcCIpCgpgYGAKCg==